package com.github.dabai.aggregation;

import java.util.List;

import org.apache.commons.lang3.builder.HashCodeBuilder;

import com.google.common.collect.Lists;

public class GroupByKey {

	private List<GroupByFieldValue<?>> fvs = Lists.newArrayList();

	public boolean containsMappingName(String name) {
		for (GroupByFieldValue<?> fv : fvs) {
			if (fv.getMapppingName().equals(name)) {
				return true;
			}
		}
		return false;
	}

	public Object getByMappingName(String name) {
		for (GroupByFieldValue<?> fv : fvs) {
			if (fv.getMapppingName().equals(name)) {
				return fv.format();
			}
		}
		return null;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void add(GroupByField<?> f, Object v) {
		if (v == null) {
			return;
		}
		GroupByFieldValue fieldValue = new GroupByFieldValue(f, v);
		fvs.add(fieldValue);
	}

	public List<GroupByFieldValue<?>> getFvs() {
		return fvs;
	}

	public void setFvs(List<GroupByFieldValue<?>> fvs) {
		this.fvs = fvs;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (GroupByFieldValue<?> fv : fvs) {
			sb.append(fv.format());
			sb.append(" ");
		}
		return sb.toString();
	}

	@Override
	public int hashCode() {
		HashCodeBuilder hb = new HashCodeBuilder(17, 87);
		for (GroupByFieldValue<?> gb : fvs) {
			hb.append(gb.format());
		}
		return hb.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		List<String> result1 = Lists.newArrayList();
		for (GroupByFieldValue<?> gb : fvs) {
			result1.add(gb.format());
		}
		GroupByKey that = (GroupByKey) obj;
		List<String> result2 = Lists.newArrayList();
		for (GroupByFieldValue<?> gb : that.getFvs()) {
			result2.add(gb.format());
		}
		return result1.containsAll(result2);
	}

	public static class GroupByFieldValue<I> {
		private GroupByField<I> groupByField;
		private I value;

		public GroupByFieldValue(GroupByField<I> groupByField, I value) {
			super();
			this.groupByField = groupByField;
			this.value = value;
		}

		public Object getMapppingName() {
			return groupByField.getMapppingName();
		}

		public GroupByField<I> getGroupByField() {
			return groupByField;
		}

		public void setGroupByField(GroupByField<I> groupByField) {
			this.groupByField = groupByField;
		}

		public Object getValue() {
			return value;
		}

		public void setValue(I value) {
			this.value = value;
		}

		public String format() {
			return groupByField.getConvert().format(value);
		}
	}
}
